<?php

namespace app\company\controller;

use app\common\controller\CompanyController;
use app\common\enum\account\PayeeType;
use app\common\enum\order\CheckStatus;
use app\common\enum\order\GoodsType;
use app\common\enum\order\OrderChanel;
use app\common\enum\order\OrderStatus;
use app\common\enum\order\OrderType;
use app\common\enum\order\ReceiveType;
use app\common\exception\BaseException;
use app\common\model\AccountRecord;
use app\common\model\CompanyWarehouse;
use app\common\model\Dealer as DealerModel;
use app\common\model\DealerGoods as DealerGoodsModel;
use app\common\model\DealerGoodsSpec;
use app\common\model\Refund;
use app\common\model\Salesman as SalesmanModel;
use app\common\model\SalesmanDealer;
use app\common\model\SalesmanStore;
use app\common\model\Store as StoreModel;
use app\common\service\annotation\ControllerAnnotation;
use app\common\service\annotation\NodeAnnotation;
use app\company\model\CompanyOrder;
use app\company\model\CompanyOrderDetail;
use app\company\model\CompanyPickOrder;
use app\company\model\CompanyPickOrderDetail;
use app\company\model\CompanyUser;
use app\company\model\DeliveryOrder;
use app\company\model\StoreBalanceLog;
use app\Request;
use jianyan\excel\Excel;
use think\App;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\response\Json;

/**
 * @ControllerAnnotation(title="订单管理")
 */
class Order extends CompanyController
{
    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model           = new CompanyOrder();
        $this->each            = true;
        $this->joinDelTable    = 'orders';
        $this->joinTable = 'detail';
        $this->importHeader    = [
            '*订单号',
            '*下单时间',
            '*经销商',
            '*业务员',
            '*门店名称',
            '是否自提(1否,2是)',
            '*订单属性(1销,2赠,3退,4换)',
            '*商品名称',
            '*商品条码',
            '*单位类型(1小单位,2大单位,3中单位)',
            '*结算方式(1现结,2账期,3预存款)',
            '*数量',
            '*销售单价',
            '*下单价',
            '*订单金额',
            '订单渠道(1后台开单,2业务员开单)',
            '退货方式(1退货退款,2仅退款)',
            '退货金额',
            '整单备注',
            '明细备注'
        ];
        $this->defaultTemplate = [
            'order_no',
            'create_time',
            'dealer_name',
            'salesman_name',
            'store_name',
            'is_self_order',
            'goods_type',
            'goods_name',
            'code69',
            'unit_type',
            'receive_type',
            'num',
            'sale_price',
            'true_price',
            'order_amount',
            'order_channel',
            'back_type',
            'return_amount',
            'order_remark',
            'detail_remark'
        ];
        $this->fileName        = '访销单导入模版';
        $this->sort            = ['create_time' => 'desc', 'id' => 'desc'];
    }

    /**
     * @NodeAnnotation(title="订单列表")
     */
    public function list(): Json
    {
        // 组合查询参数
        list($limit, $where) = $this->buildSearchParams();
        $is_cx = $this->request->get('is_cx', 1);
        if ($is_cx == 1) {
            $where[] = ['pid', '=', 0];
        } else {
            $where[] = ['pid', '<>', 0];
        }
        // 获取列表数据
        $sql            = $this->model
            ->where($where)
            ->where($this->defaultWhere)
            ->with([
                'store',
                'dealer',
                'salesman',
                'orders'    => function (Query $query) {
                    $query->field('id,pid,order_type');
                },
                'detailAll' => function (Query $query) {
                    $query->with([
                        'goods'     => function ($query) {
                            $query->withTrashed();
                        },
                        'goodsSpec' => function ($query) {
                            $query->withTrashed();
                        },
                        'warehouse'
                    ]);
                },
                'detail' => function (Query $query) {
                    $query->with([
                        'goods'     => function ($query) {
                            $query->withTrashed();
                        },
                        'goodsSpec' => function ($query) {
                            $query->withTrashed();
                        },
                        'warehouse'
                    ]);
                }
            ]);
        $amount         = $sql->value('SUM(order_amount)');
        $list           = $sql->order($this->sort)->paginate($limit)
            ->each(function ($vo) {
                $vo->sale_amount = round($vo->order_amount - $vo->return_amount,2);
                $vo->creator = (new CompanyUser())->where('id', $vo->creator_id)->value('username') ?? '无';
                $vo->auditor = (new CompanyUser())->where('id', $vo->auditor_id)->value('username') ?? '无';
                $vo->appointment_time = $vo->appointment_time ? date('Y-m-d H:i:s', $vo->appointment_time) : '暂无';
            })->toArray();
        $list['amount'] = $amount;
        return $this->success($list);
    }

    /**
     * @NodeAnnotation(title="系统开单")
     * TODO 逻辑有空拆分，优化一下，另外需要加上事务锁，队列开单，前端防抖，避免并发
     */
    public function add(Request $request): Json
    {
        try {
            $this->checkPost();
            $post = $request->post();
            $rule = [
                'dealer_id|经销商'       => 'require',
                'store_id|门店'          => 'require',
                'salesman_id|业务员'     => 'require',
                'check_status|审核状态'  => 'require',
                'is_self_order|是否自提' => 'require',
                'detail|下单商品'        => 'require',
            ];
            $this->validate($post, $rule);
            $this->model->transaction(function () use ($post) {
                // 处理订单商品信息数据
                $detail = $this->dealOrderDetail($post);

                // 订单公共信息组装
                $commonOrder = $this->commonOrder($post);

                // 使用 array_filter 筛选出 goods_type 获取销售金额
                $xsAmountArray = array_filter($detail, function ($item) {
                    return $item['goods_type'] == GoodsType::SALE;
                });

                // 2024.12.02 新增判断库存
                $this->checkStock($xsAmountArray);

                // 使用 array_filter 筛选出 goods_type 获取退款金额
                $returnAmountArray = array_filter($detail, function ($item) {
                    return in_array($item['goods_type'], [GoodsType::RETURN_GOODS, GoodsType::CHANGE_GOODS]);
                });

                // 主订单信息
                $order             = $commonOrder;
                $order['order_no'] = generateOrderNo('KD');
                // 订单金额
                $order['order_amount'] = array_sum(array_column(
                    $xsAmountArray,
                    'total_price'
                )) + array_sum(array_column(
                    $returnAmountArray,
                    'total_price'
                ));
                // 退款金额
                $order['return_amount'] = array_sum(array_column($returnAmountArray, 'total_price'));
                // 未结算金额
                $order['unsay_amount'] = $order['order_amount'];

                // 子订单信息
                $info = $commonOrder;
                // 所有类型
                $goodsType = array_column($detail, 'goods_type');
                // 销售单
                $childOrder = [];
                if (in_array(GoodsType::SALE, $goodsType) || in_array(GoodsType::GIFT, $goodsType)) {
                    $info['order_no']      = $order['order_no'] . '-' . OrderType::SALES;
                    $info['order_type']    = OrderType::SALES;
                    $info['order_amount']  = array_sum(array_column($xsAmountArray, 'total_price'));
                    $info['return_amount'] = 0;
                    $info['unsay_amount']  = array_sum(array_column($xsAmountArray, 'total_price'));
                    $childOrder[]          = $info;
                }

                // 回库单
                if (in_array(GoodsType::RETURN_GOODS, $goodsType) || in_array(GoodsType::CHANGE_GOODS, $goodsType)) {
                    $info['order_no']      = $order['order_no'] . '-' . OrderType::RETURN;
                    $info['order_type']    = OrderType::RETURN;
                    $info['order_amount']  = $order['return_amount'];
                    $info['return_amount'] = $order['return_amount'];
                    $info['unsay_amount']  = $order['return_amount'];
                    $childOrder[]          = $info;
                    // 2024.11.14 生成退款单和增加金额
                    $refundData = $this->dealAccountRecord($order, $post);
                }
                // 保存主订单
                $save = $this->model->save($order);

                if ($save) {
                    // 关联主订单ID
                    $childOrder = array_map(function ($vo) {
                        $vo['pid'] = $this->model->id;
                        return $vo;
                    }, $childOrder);
                    $this->model->saveAll($childOrder);
                }

                // 保存退款单
                if (!empty($refundData)) {
                    $companyOrderId = $this->model->where('pid', $this->model->id)
                        ->where('order_type', OrderType::RETURN)->value('id');
                    if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                    $refundData['company_order_pid'] = $this->model->id;
                    $refundData['company_order_id']  = $companyOrderId;
                    (new Refund())->save($refundData);
                }

                // 保存订单详情
                $detail = $this->dealDetailOrder($detail, $order['dealer_id'],$post);
                (new CompanyOrderDetail())->saveAll($detail);
                // 如果对应订单内是预存款结算，需要把预存款转入冻结金额字段
                $this->dealYc($post, $xsAmountArray);
            });
        } catch (\Exception $e) {
            return $this->error('开单失败' . $e->getMessage());
        }
        return $this->success('开单成功');
    }

    private function checkStock($xsAmountArray): void
    {
        $goodsArray = arrayGroupBy($xsAmountArray, function ($item) {
            return $item['dealer_goods_id'];
        });
        foreach ($goodsArray as $key => $goods) {
            $goodsInfo = (new DealerGoodsModel())->where('id', $key)->find();
            $orderNum  = 0;
            foreach ($goods as $spec) {
                $specInfo = (new DealerGoodsSpec())->where('id', $spec['dealer_goods_spec_id'])->find();
                if (!$specInfo['ratio']) throw new BaseException(['message' => '请先维护【' . $goodsInfo['name'] . '】换算比例']);
                $orderNum += $spec['num'] * $specInfo['ratio'];
            }
            if ($orderNum > $goodsInfo['sales_stock']) throw new BaseException(['message' => $goodsInfo['name'] . '库存不足']);
        }
    }

    /**
     * 处理订单金额信息
     */
    private function dealOrderDetail(mixed $post): array
    {
        return array_map(function ($vo) {
            if ($vo['num'] <= 0) throw new BaseException(['message' => '数量不能小于0']);
            $vo['true_price']  = match ($vo['goods_type']) {
                GoodsType::GIFT                                  => 0, // 赠送金额0
                GoodsType::RETURN_GOODS, GoodsType::CHANGE_GOODS => -$vo['true_price'] ?? -$vo['sale_price'],
                default                                          => $vo['true_price']
            };
            $vo['total_price'] = $vo['true_price'] * $vo['num'];
            return $vo;
        }, json_decode($post['detail'], true));
    }

    /**
     * 订单公共信息
     * @param mixed $post
     * @return array
     */
    private function commonOrder(mixed $post): array
    {
        // 订单公共信息
        return [
            'company_id'    => $this->companyId,
            'dealer_id'     => $post['dealer_id'],
            'salesman_id'   => $post['salesman_id']?? 0,
            'store_id'      => $post['store_id']??0,
            'receive_type'  => $post['receive_type'] ?? 0,
            'remark'        => $post['remark'] ?? '',
            'order_status'  => $post['order_status'] ?? 1,
            'pay_status'    => $post['pay_status'] ?? 1,
            'is_self_order' => $post['is_self_order'] ?? 1,
            'check_status'  => $post['check_status'] ?? 1,
            'order_channel' => OrderChanel::ADMIN,
            'creator_id' => $this->uid,
            'auditor_id' => $post['check_status'] == 1 ? 0 : $this->uid,
            'appointment_time' => isset($post['appointment_time']) ? strtotime($post['appointment_time']) : 0,
        ];
    }

    public function dealAccountRecord($order, $post): array
    {
        $accountModel = new AccountRecord();
        $accountInfo  = $accountModel->where('company_id', $this->companyId)
            ->where('payee_type', AccountRecord::SALESMAN)
            ->where('payee_id', $post['salesman_id'])->find();
        if (!$accountInfo) {
            $accountData = [
                'company_id'   => $this->companyId,
                'payee_type'   => AccountRecord::SALESMAN,
                'payee_id'     => $post['salesman_id'],
                'return_money' => $order['return_amount'],
            ];
            $accountModel->save($accountData);
            $accountId = $accountModel->getKey();
        } else {
            $accountInfo->inc('return_money', $order['return_amount'])->save();
            $accountId = $accountInfo->id;
        }
        return [
            'account_record_id' => $accountId,
            'company_id'        => $this->companyId,
            'salesman_id'       => $post['salesman_id'],
            'store_id'          => $post['store_id'],
            'money'             => $order['return_amount'],
        ];
    }

    /**
     * 处理订单详情
     * @param array $detail
     * @return array
     * @throws BaseException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function dealDetailOrder(array $detail, $dealer_id,$post): array
    {
        $driver_money        = 0;
        $assist_driver_money = 0;
        $detail              = array_map(function ($vo) use (&$driver_money, &$assist_driver_money, &$xsCompanyOrderId, $dealer_id,$post) {
            $vo['dealer_id'] = $dealer_id;
            if ($vo['goods_type'] == GoodsType::SALE || $vo['goods_type'] == GoodsType::GIFT) {
                // 查询销售类型主键
                if (empty($vo['id'])) {
                    $companyOrderId = $this->model->where('pid', $this->model->id)
                        ->where('order_type', OrderType::SALES)->value('id');
                    if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                    $vo['company_order_id'] = $companyOrderId;
                    $vo['company_order_pid'] =  $this->model->id;
                }
                // 查询库存量
                $stockInfo                 = (new DealerGoodsSpec())->where('id', $vo['dealer_goods_spec_id'])
                    ->field('stock,freeze_stock,driver_money,assist_driver_money,ratio,virtual_sales,actual_sales')
                    ->find();
                $vo['driver_money']        = $post['is_self_order']== 1 ? bcmul($stockInfo['driver_money'] ?? 0, $vo['num'] ?? 0, 2) : 0;
                $vo['assist_driver_money'] = $post['is_self_order']== 1 ? bcmul($stockInfo['assist_driver_money'] ?? 0, $vo['num'] ?? 0, 2) : 0;
                $driver_money              = bcadd(
                    $driver_money,
                    bcmul($stockInfo['driver_money'] ?? 0, $vo['num'] ?? 0, 2),
                    2
                );
                $assist_driver_money       = bcadd(
                    $assist_driver_money,
                    bcmul($stockInfo['assist_driver_money'] ?? 0, $vo['num'] ?? 0, 2),
                    2
                );
                //                if ($stockInfo['stock'] < $vo['num']) throw new BaseException(['message' => '库存不足']);

                // 增加经销商商品销量
                if (!empty($vo['id'])) {
                    //获取原来详情表num
                    $company_detail_model =   new CompanyOrderDetail();
                    $num =  $company_detail_model->where('id', $vo['id'])->value('num');
                    if ($vo['num'] - $num > 0) {
                        //num大于o 说明 要增加售卖量
                        $new_num = $vo['num'] - $num;
                        $stockInfo->inc('virtual_sales', $new_num)
                            ->inc('actual_sales', $new_num)
                            ->save();
                        (new DealerGoodsModel())->where('id', $vo['dealer_goods_id'])
                            ->inc('virtual_sales', $new_num * $stockInfo['ratio'])
                            ->inc('actual_sales', $new_num * $stockInfo['ratio'])
                            ->dec('sales_stock', $new_num * $stockInfo['ratio'])
                            ->save();
                    } else {
                        //减少售卖量
                        $new_num = abs($vo['num'] - $num);
                        $stockInfo->inc('virtual_sales', $new_num)
                            ->dec('actual_sales', $new_num)
                            ->save();
                        (new DealerGoodsModel())->where('id', $vo['dealer_goods_id'])
                            ->dec('virtual_sales', $new_num * $stockInfo['ratio'])
                            ->dec('actual_sales', $new_num * $stockInfo['ratio'])
                            ->inc('sales_stock', $new_num * $stockInfo['ratio'])
                            ->save();
                    }
                } else {
                    $stockInfo->inc('virtual_sales', $vo['num'])
                        ->inc('actual_sales', $vo['num'])
                        ->save();
                    (new DealerGoodsModel())->where('id', $vo['dealer_goods_id'])
                        ->inc('virtual_sales', $vo['num'] * $stockInfo['ratio'])
                        ->inc('actual_sales', $vo['num'] * $stockInfo['ratio'])
                        ->dec('sales_stock', $vo['num'] * $stockInfo['ratio'])
                        ->save();
                }

            
            }
            if (empty($vo['id'])) {
            if ($vo['goods_type'] == GoodsType::RETURN_GOODS || $vo['goods_type'] == GoodsType::CHANGE_GOODS) {
                // 查询回库类型主键
                $companyOrderId = $this->model->where('pid', $this->model->id)
                    ->where('order_type', OrderType::RETURN)->value('id');
                if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                $vo['company_order_id'] = $companyOrderId;
                $vo['company_order_pid'] =  $this->model->id;
            }
        }
            $vo['real_num'] = $vo['num'];
            $vo['company_id'] =  $this->companyId;
            return $vo;
        }, $detail);

        // 回填司机配送收益
        if($post['is_self_order'] == 2) {
            $driver_money = 0;
            $assist_driver_money = 0;
        }
        $this->model->where('pid', $this->model->id)
            ->where('order_type', OrderType::SALES)
            ->save(['driver_money' => $driver_money, 'assist_driver_money' => $assist_driver_money]);
        return $detail;
    }

    private function dealYc($post, $xsAmountArray): void
    {
        if ($post['receive_type'] == ReceiveType::YC) {
            $orderMoney        = round(array_sum(array_column($xsAmountArray, 'total_price')), 2);
            $salesmanStoreInfo = (new SalesmanStore())->where('store_id', $post['store_id'])
                ->where('salesman_id', $post['salesman_id'])->find();
            $oldBalance        = $salesmanStoreInfo['balance'];
            $oldFreeze         = $salesmanStoreInfo['freeze'];
            //如果修改过的订单金额大于修改前的订单金额 则增加余额
            if (!empty($post['id'])) {
                //通过订单id获取订单金额
                $companyOrderModel = new CompanyOrder();
                $oldOrderMoney = $companyOrderModel->where('id', $post['id'])
                    ->value('order_amount');
                $cz = $orderMoney - $oldOrderMoney;
                if ($orderMoney > $oldOrderMoney) {
                    $salesmanStoreInfo->inc('balance',  $cz)->save();
                } else {
                    $salesmanStoreInfo->dec('balance',  abs($cz))->save();
                }
            } else {
                $salesmanStoreInfo->inc('balance', $orderMoney)->save();
            }
            $companyOrderId = $this->model->where('pid', $this->model->id)->where('order_type', OrderType::SALES)
                ->value('id');
            $this->model->where('id', $companyOrderId)->save(['yc_money' => $orderMoney]);
            // 生成余额变动记录
            if (!empty($post['id'])) {
                (new StoreBalanceLog())->where('company_order_id', $companyOrderId)->delete();
            }
            $data = [
                'company_id'       => $this->companyId,
                'salesman_id'      => $post['salesman_id'],
                'store_id'         => $post['store_id'],
                'creator_type'     => StoreBalanceLog::TYPE_SALESMAN,
                'creator_id'       => $post['salesman_id'],
                'company_order_id' => $companyOrderId,
                'old_balance'      => $oldBalance,
                'new_balance'      => bcsub($oldBalance, $orderMoney, 2),
                'old_freeze'       => $oldFreeze,
                'new_freeze'       => bcadd($oldFreeze, $orderMoney, 2),
                'remark'           => StoreBalanceLog::REMARK_ORDER,
            ];
            (new StoreBalanceLog())->save($data);
        }
    }

    public function dealYc1($post, $orderMoney): void
    {
        if ($post['receive_type'] == ReceiveType::YC) {
            $salesmanStoreInfo = (new SalesmanStore())->where('store_id', $post['store_id'])
                ->where('salesman_id', $post['salesman_id'])->find();
            $oldBalance        = $salesmanStoreInfo['balance'];
            $oldFreeze         = $salesmanStoreInfo['freeze'];
            if ($salesmanStoreInfo['balance'] < $orderMoney) $orderMoney = $salesmanStoreInfo['balance'];
            $salesmanStoreInfo->dec('balance', $orderMoney)->inc('freeze', $orderMoney)->save();
            $companyOrderId = $this->model->where('pid', $this->model->id)->where('order_type', OrderType::SALES)
                ->value('id');
            $this->model->where('id', $companyOrderId)->save(['yc_money' => $orderMoney]);
            // 生成余额变动记录
            $data = [
                'company_id'       => $this->companyId,
                'salesman_id'      => $post['salesman_id'],
                'store_id'         => $post['store_id'],
                'creator_type'     => StoreBalanceLog::TYPE_SALESMAN,
                'creator_id'       => $post['salesman_id'],
                'company_order_id' => $companyOrderId,
                'old_balance'      => $oldBalance,
                'new_balance'      => bcsub($oldBalance, $orderMoney, 2),
                'old_freeze'       => $oldFreeze,
                'new_freeze'       => bcadd($oldFreeze, $orderMoney, 2),
                'remark'           => StoreBalanceLog::REMARK_ORDER,
            ];
            (new StoreBalanceLog())->save($data);
        }
    }

    /**
     * @NodeAnnotation (title="编辑订单详情")
     * @param Request $request
     * @param int $id
     * @return Json
     * @throws BaseException
     */
    public function edit(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $rule = [
            'id' => 'require|integer'
        ];
        $this->validate($post, $rule);
        try {
            if (isset($post['detail'])) {
              
                $row = $this->model->find($post['id']);
                if (!$row) return $this->error('数据不存在！');
                if($row['check_status']==2){
                    return $this->error('订单已审核通过，不能修改！');
                }
                try {
                    $this->model->transaction(function () use ($post, $row) {


                        // 处理订单商品信息数据
                        $detail = $this->dealOrderDetail($post);

                        // 使用 array_filter 筛选出 goods_type 获取销售金额
                        $xsAmountArray = array_filter($detail, function ($item) {
                            return $item['goods_type'] == GoodsType::SALE;
                        });

                        // 2024.12.02 新增判断库存
                        $this->checkStock($xsAmountArray);

                        // 使用 array_filter 筛选出 goods_type 获取退款金额
                        $returnAmountArray = array_filter($detail, function ($item) {
                            return in_array($item['goods_type'], [GoodsType::RETURN_GOODS, GoodsType::CHANGE_GOODS]);
                        });
                        $commonOrder = $this->commonOrder($post);
                        $order             = $commonOrder;
                        // 订单金额
                        $order['order_amount'] = array_sum(array_column(
                            $xsAmountArray,
                            'total_price'
                        )) + array_sum(array_column(
                            $returnAmountArray,
                            'total_price'
                        ));
                        // 退款金额
                        $order['return_amount'] = array_sum(array_column($returnAmountArray, 'total_price'));
                        // 未结算金额
                        $order['unsay_amount'] = $order['order_amount'];
                        $order['id'] = $post['id'];
                        $row->save($order);
                        // halt( $row->fetchSql(true)->save($order));
                        // 所有类型
                        $goodsType = array_column($detail, 'goods_type');
                        // 销售单
                        // 子订单信息
                        $info = [];
                        $childOrder = [];
                        if (in_array(GoodsType::SALE, $goodsType) || in_array(GoodsType::GIFT, $goodsType)) {
                            $info['order_type']    = OrderType::SALES;
                            $info['order_amount']  = array_sum(array_column($xsAmountArray, 'total_price'));
                            $info['return_amount'] = 0;
                            $info['unsay_amount']  = array_sum(array_column($xsAmountArray, 'total_price'));
                        }

                        // 回库单
                        if (in_array(GoodsType::RETURN_GOODS, $goodsType) || in_array(GoodsType::CHANGE_GOODS, $goodsType)) {
                            $info['order_type']    = OrderType::RETURN;
                            $info['order_amount']  = $order['return_amount'];
                            $info['return_amount'] = $order['return_amount'];
                            $info['unsay_amount']  = $order['return_amount'];

                            // 2024.11.14 生成退款单和增加金额
                            $refundData = $this->dealAccountRecord($order, $post);
                        }
                        $childOrder[]          = $info;
                        $childOrder = array_map(function ($vo) {
                            $vo['pid'] = $this->model->id;
                            return $vo;
                        }, $childOrder);
                        $this->model->saveAll($childOrder);
                        // 保存退款单
                        if (!empty($refundData)) {
                            $companyOrderId = $this->model->where('pid', $this->model->id)
                                ->where('order_type', OrderType::RETURN)->value('id');
                            if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                            $refundData['company_order_pid'] = $this->model->id;
                            $refundData['company_order_id']  = $companyOrderId;
                            (new Refund())->save($refundData);
                        }

                        // 保存订单详情
                        $detail = $this->dealDetailOrder($detail, $order['dealer_id'],$post);
                        // halt($detail);
                        (new CompanyOrderDetail())->saveAll($detail);
                        // 如果对应订单内是预存款结算，需要把预存款转入冻结金额字段
                        $this->dealYc($post, $xsAmountArray);
                    });
                } catch (\Exception $e) {
                    return $this->error('保存失败:' . $e->getMessage() . $e->getLine());
                }
                return $this->success('保存成功');
            } else {
                $detailModel = new CompanyOrderDetail();
                $detail      = $detailModel->find($post['id']);
                $detail->save([
                    'num'         => $post['num'],
                    'true_price'  => $post['true_price'],
                    'total_price' => $post['num'] * $post['true_price'],
                ]);
            }
        } catch (\Exception $e) {
            return $this->error('编辑失败:' . $e->getMessage() . $e->getLine());
        }
        return $this->success('编辑成功');
    }

    /**
     * @NodeAnnotation (title="修改字段")
     * @param Request $request
     * @return Json
     * @throws BaseException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function modify(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $info = $this->model->find($post['id']);
        $rule = [
            'id' => 'require|integer',
        ];
        $this->validate($post, $rule);
        if (!$info) return $this->error('订单信息有误');
        if ($post['field'] == 'order_status') {
            try {
                $this->model->transaction(function () use ($post) {
                    $this->model->where('id', $post['id'])->save(['order_status' => $post['value']]);
                    $this->model->where('pid', $post['id'])->save(['order_status' => $post['value']]);
                });
            } catch (\Exception $e) {
                return $this->error('修改失败' . $e->getMessage());
            }
        }
        return $this->success('修改成功');
    }

    /**
     * @NodeAnnotation(title="审核")
     */
    public function check(Request $request): Json
    {
        try {
            $this->checkPost();
            $post = $request->post();
            $rule = [
                'id|订单ID' => 'require',
            ];
            $post['auditor_id'] = $this->uid;
            $this->validate($post, $rule);
            $info = $this->model->where('id', $post['id'])->find();
            if (!$info || $info->check_status != CheckStatus::NO_CHECK) return $this->error('订单信息有误');
            $this->model->transaction(function () use ($post) {
                $this->model->where('id', $post['id'])
                    ->save(['check_status' => CheckStatus::YES_CHECK]);
                $this->model->where('pid', $post['id'])
                    ->save(['check_status' => CheckStatus::YES_CHECK]);
            });
        } catch (\Exception $e) {
            return $this->error('审核失败' . $e->getMessage());
        }
        return $this->success('审核成功');
    }

    /**
     * @NodeAnnotation(title="导入")
     * @throws BaseException
     */
    public function import(Request $request): Json
    {
        $this->checkPost();
        $file = $request->file('file');
        if (!$file) return $this->error('请上传文件！');
        // 保存文件到临时目录
        $savePath = $file->move('storage' . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR);
        // 获取文件的完整路径
        $savePath = $savePath->getPathname();
        $this->model->startTrans();
        try {
            $data = Excel::import($savePath, 1, false, 'Xlsx', './storage/temp/excelImg/');
            if (!$data) throw new BaseException(['message' => '文件内容为空！']);
            if (!$this->importHeader) throw new BaseException(['message' => '请联系管理设置文件模版！']);
            if (array_filter($data[0]) != $this->importHeader) throw new BaseException(['message' => '文件模版错误！']);
            // 去掉表头
            unset($data[0]);
            $data = array_filter($data);
            $orders = $this->verify_import($data);
            $this->dealOrder($orders);
        } catch (\Exception $e) {
            @unlink($savePath);
            $this->model->rollback();
            return $this->error('导入失败' . $e->getMessage());
        }
        @unlink($savePath);
        $this->model->commit();
        return $this->success('导入成功！');
    }
    public function verify_import($data)
    {
        if (empty($data)) throw new BaseException(['message' => '文件内容为空！']);
        $orders = array_map(function ($vo) {
            $fields = $this->defaultTemplate;
            $data   = array_combine($fields, $vo);
            // 验证表格中的值
            $rule = [
                'order_no|订单号'       => 'require',
                'create_time|下单时间'  => 'require',
                'dealer_name|经销商'    => 'require',
                'salesman_name|业务员'  => 'require',
                'store_name|门店名称'   => 'require',
                'goods_type|订单属性'   => 'require',
                'goods_name|商品名称'   => 'require',
                'code69|商品条码'       => 'require',
                'unit_type|单位类型'    => 'require',
                'receive_type|结算方式' => 'require',
                'num|数量'              => 'require',
                'sale_price|销售单价'   => 'require',
                'true_price|下单价'     => 'require',
                'order_amount|订单金额' => 'require',
            ];
            $this->validate($data, $rule);
            return $data;
        }, $data);
        return $orders;
    }
    public function dealOrder(mixed $orders): void
    {

        // 订单号去重
        $orderNos = array_unique(array_column($orders, 'order_no'));
        foreach ($orderNos as $orderNo) {
            // 匹配订单
            $filteredArray = array_filter($orders, function ($item) use ($orderNo) {
                return $item['order_no'] === $orderNo;
            });
            // 重组
            $orderData = array_values($filteredArray);
            //                        halt($orderData);
            // 订单公共信息
            $commonOrder              = [
                'company_id'    => $this->companyId,
                'order_no'      => $orderNo,
                'create_time'   => strtotime($orderData[0]['create_time']),
                'receive_type'  => $orderData[0]['receive_type'] ?? 1,
                'remark'        => $orderData[0]['order_remark'] ?? '',
                'is_self_order' => $orderData[0]['is_self_order'] ?? 1,
                'check_status'  => CheckStatus::YES_CHECK,
                'order_channel' => 1,
            ];
            $commonOrder['dealer_id'] = DealerModel::where('company_id', $this->companyId)
                ->where('name', $orderData[0]['dealer_name'])
                ->value('id');
            if (!$commonOrder['dealer_id']) throw new BaseException(["message" => "经销商【{$orderData[0]['dealer_name']}】不存在！"]);

            $commonOrder['salesman_id'] = SalesmanModel::where('company_id', $this->companyId)
                ->where('rename', $orderData[0]['salesman_name'])
                ->value('id');
            if (!$commonOrder['salesman_id']) throw new BaseException(["message" => "业务员【{$orderData[0]['salesman_name']}】不存在！"]);

            $commonOrder['store_id'] = StoreModel::where('company_id', $this->companyId)
                ->where('name', $orderData[0]['store_name'])
                ->value('id');
            if (!$commonOrder['store_id']) throw new BaseException(["message" => "门店【{$orderData[0]['store_name']}】不存在！"]);

            // 主订单
            $order = $commonOrder;
            // 订单金额
            $order['order_amount'] = array_sum(array_column($orderData, 'order_amount'));
            // 退款金额
            $order['return_amount'] = array_sum(array_column($orderData, 'return_amount'));
            // 子订单
            $info       = $commonOrder;
            $childOrder = [];
            // 根据类型组装子订单
            $goodsType = array_column($orderData, 'goods_type');
            // 销售单
            $xsOrderArray = array_filter($orderData, function ($item) {
                return in_array($item['goods_type'], [GoodsType::SALE, GoodsType::GIFT]);
            });

            if (in_array(GoodsType::SALE, $goodsType) || in_array(GoodsType::GIFT, $goodsType)) {
                $info['order_no']      = $order['order_no'] . '-' . OrderType::SALES;
                $info['order_type']    = OrderType::SALES;
                $info['order_amount']  = array_sum(array_column($xsOrderArray, 'order_amount'));
                $info['return_amount'] = 0;
                $info['unsay_amount']  = $info['order_amount'];
                $unitNum               = 0;
                $details               = array_map(function ($vo) use ($info, &$unitNum) {
                    $detail                    = [
                        'goods_type'  => $vo['goods_type'],
                        'true_price'  => $vo['true_price'],
                        'num'         => $vo['num'],
                        'total_price' => $vo['order_amount'],
                        'remark'      => $vo['detail_remark']
                    ];
                    $goodsInfo                 = DealerGoodsModel::where('dealer_id', $info['dealer_id'])
                        ->where('name', $vo['goods_name'])
                        ->find();
                    $detail['dealer_goods_id'] = $goodsInfo->id ?? '';

                    if (!$detail['dealer_goods_id']) throw new BaseException(["message" => "经销商【{$vo['dealer_name']}】商品【{$vo['goods_name']}】不存在！"]);

                    $detail['dealer_goods_spec_id'] = DealerGoodsSpec::where(
                        'dealer_goods_id',
                        $detail['dealer_goods_id']
                    )
                        ->where('unit_type', $vo['unit_type'])
                        ->value('id') ?? '';
                    if (!$detail['dealer_goods_spec_id']) throw new BaseException(["message" => "经销商【{$vo['dealer_name']}】商品【{$vo['goods_name']}】规格单位【{$vo['unit_type']}】不存在！"]);
                    // TODO 仓库后期需要选择录入
                    $detail['company_warehouse_id'] = CompanyWarehouse::where('company_id', $this->companyId)
                        ->value('id');

                    $specInfo = DealerGoodsSpec::where('id', $detail['dealer_goods_spec_id'])
                        ->find();

                    $unitNum += $specInfo->ratio * $vo['num'];

                    $detail['driver_money']        = $specInfo->driver_money * $vo['num'];
                    $detail['assist_driver_money'] = $specInfo->assist_driver_money * $vo['num'];

                    $specInfo->inc('actual_sales', $vo['num'])
                        ->inc('virtual_sales', $vo['num'])
                        ->save();

                    return $detail;
                }, $xsOrderArray);

                $info['driver_money']        = array_sum(array_column($details, 'driver_money'));
                $info['assist_driver_money'] = array_sum(array_column($details, 'assist_driver_money'));
                $totalUnitNum                = $unitNum;
                // 获取当前$details 中的 dealer_goods_id;
                $dealerGoodsId = array_unique(array_column($details, 'dealer_goods_id'));
                // 判断库存
                $goodsInfo = (new DealerGoodsModel())->where('id', implode(',', $dealerGoodsId))->find();
                if ($totalUnitNum > $goodsInfo->sales_stock) throw new BaseException(["message" => "商品【{$goodsInfo->name}】剩余库存不足本次导入！"]);
                // 扣减库存
                $goodsInfo->inc('virtual_sales', $totalUnitNum)
                    ->inc('actual_sales', $totalUnitNum)
                    ->dec('sales_stock', $totalUnitNum)
                    ->save();
                $info['detail'] = $details;
                $childOrder[]   = $info;
            }

            // 回库单
            if (in_array(GoodsType::RETURN_GOODS, $goodsType) || in_array(GoodsType::CHANGE_GOODS, $goodsType)) {
                $info['order_no']      = $order['order_no'] . '-' . OrderType::RETURN;
                $info['order_type']    = OrderType::RETURN;
                $info['order_amount']  = array_sum(array_column($orderData, 'return_amount'));
                $info['return_amount'] = $info['order_amount'];
                $info['unsay_amount']  = $info['order_amount'];
                // 组装退款单信息
                $returnAmountArray = array_filter($orderData, function ($item) {
                    return in_array($item['goods_type'], [GoodsType::RETURN_GOODS, GoodsType::CHANGE_GOODS]);
                });
                $details           = array_map(function ($vo) use ($info) {
                    $detail                    = [
                        'goods_type'  => $vo['goods_type'],
                        'true_price'  => $vo['true_price'],
                        'num'         => $vo['num'],
                        'real_num'    => $vo['num'],
                        'total_price' => $vo['order_amount'],
                        'remark'      => $vo['detail_remark']
                    ];
                    $detail['dealer_goods_id'] = DealerGoodsModel::where('dealer_id', $info['dealer_id'])
                        ->where('name', $vo['goods_name'])
                        ->value('id') ?? '';
                    if (!$detail['dealer_goods_id']) throw new BaseException(["message" => "经销商【{$vo['dealer_name']}】商品【{$vo['goods_name']}】不存在！"]);

                    $detail['dealer_goods_spec_id'] = DealerGoodsSpec::where(
                        'dealer_goods_id',
                        $detail['dealer_goods_id']
                    )
                        ->where('unit_type', $vo['unit_type'])
                        ->value('id') ?? '';
                    if (!$detail['dealer_goods_spec_id']) throw new BaseException(["message" => "经销商【{$vo['dealer_name']}】商品【{$vo['goods_name']}】规格单位【{$vo['unit_type']}】不存在！"]);
                    // TODO 仓库后期需要选择录入
                    $detail['company_warehouse_id'] = CompanyWarehouse::where('company_id', $this->companyId)
                        ->value('id');
                    return $detail;
                }, $returnAmountArray);

                $account        = ['return_amount' => $info['return_amount']];
                $userInfo       = ['salesman_id' => $info['salesman_id'], 'store_id' => $info['store_id']];
                $info['detail'] = $details;
                $childOrder[]   = $info;
                // 2024.11.14 生成退款单和增加金额
                $refundData = $this->dealAccountRecord($account, $userInfo);
            }
            // 新增主订单
            $orderModel = new CompanyOrder();
            $save       = $orderModel->save($order);
            if (!$save) throw new BaseException(["message" => "订单保存失败！"]);
            // 新增子订单
            $childOrder     = array_map(function ($vo) use ($orderModel) {
                $vo['pid'] = $orderModel->id;
                return $vo;
            }, $childOrder);
            $childOrderInfo = $orderModel->saveAll($childOrder);
            // 保存退款单
            if (!empty($refundData)) {
                $companyOrderId = $orderModel->where('pid', $orderModel->id)
                    ->where('order_type', OrderType::RETURN)->value('id');
                if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                $refundData['company_order_pid'] = $orderModel->id;
                $refundData['company_order_id']  = $companyOrderId;
                (new Refund())->save($refundData);
            }
            // 保存订单详情
            $childOrderInfo = $childOrderInfo->toArray();
            array_walk($childOrderInfo, function ($v) {
                $detail = $v['detail'];
                foreach ($detail as &$item) {
                    $item['company_order_id']  = $v['id'];
                    $item['company_order_pid'] = $v['pid'];
                }
                // 新增订单详情
                (new CompanyOrderDetail())->insertAll($detail);
            });
            // 如果对应订单内是预存款结算，需要把预存款转入冻结金额字段
            $userInfo   = ['receive_type' => $commonOrder['receive_type'], 'salesman_id' => $commonOrder['salesman_id'], 'store_id' => $commonOrder['store_id']];
            $orderMoney = array_sum(array_column($xsOrderArray, 'order_amount'));
            $this->dealYc1($userInfo, $orderMoney);
        }
    }

    /**
     * @NodeAnnotation(title="删除订单")
     * @param Request $request
     * @return Json
     * @throws BaseException
     */
    public function del(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $rule  = [
            'id' => 'require'
        ];
        $this->validate($post, $rule);
        $ids = explode(',', $post['id']);
        try {
            foreach ($ids as $v) {
                $sql = $this->model;
                $outStatus = $sql->where('pid', $v)->value('out_status');
                if($outStatus == 2) throw new BaseException(['message' => '订单已出库']);
                if ($this->joinDelTable) {
                    // 关联删除
                    $row = $sql->with(explode(',', $this->joinDelTable))->find($v);
                    if ($row) $row->together(explode(',', $this->joinDelTable))->delete();
                } else {
                    $row = $sql->find($v);
                    $row->delete();
                }

                // 2024.12.27 修改已取消的订单删除时不再重复回调库存
                if($row->order_status != 3){
                    // 查询订单详情，回退库存
                    $detail = (new CompanyOrderDetail())->where('company_order_pid', $v)->select();
                    foreach ($detail as $item) {
                        $goods = (new \app\common\model\DealerGoods())->find($item['dealer_goods_id']);
                        $spec = (new \app\common\model\DealerGoodsSpec())->find($item['dealer_goods_spec_id']);
                        $goods->save(['sales_stock' => $goods['sales_stock'] + ($item['num'] * $spec['ratio'])]);
                    }
                }

                // 删除订单后，如果对应有拣货单内容，需要把拣货单内此数据剔除
                $sonOrderId = (new CompanyOrder())->where('pid', $v)->where('order_type',OrderType::SALES)->withTrashed()->value('id');
                $pickDetail = (new CompanyPickOrderDetail())->where('company_order_id', $sonOrderId)->find();
                if($pickDetail){
                    $pick = (new CompanyPickOrder())->where('id',$pickDetail->company_pick_order_id)->find();
                    $goodsNum = (new CompanyOrderDetail())->where('company_order_id',$sonOrderId)->sum('num');
                    $orderIds = array_diff(explode(',',$pick['company_order_ids']),[$sonOrderId]);
                    $pickDetail->delete();
                    $pick->save([
                        'pick_num' => $pick['pick_num'] - $goodsNum,
                        'true_pick_num' => $pick['true_pick_num'] - $goodsNum,
                        'order_num' => $pick['order_num'] - 1,
                        'company_order_ids'=>implode(',',$orderIds)
                    ]);
                }
                // 删除订单后，如果对应有配送单内容，需要把配送单内此数据剔除
                $deliveryDetail = (new DeliveryOrder())->where('company_order_id', $sonOrderId)->find();
                if($deliveryDetail){
                    $delivery = (new \app\company\model\Delivery())->where('id',$deliveryDetail->delivery_id)->find();
                    $goodsNum = (new CompanyOrderDetail())->where('company_order_id',$sonOrderId)->sum('num');
                    $orderIds = array_diff(explode(',',$delivery['company_order_ids']),[$sonOrderId]);
                    $shopNum = (new CompanyOrder())->field('store_id')->where('id', 'in', $orderIds)->group('store_id')->count();
                    $deliveryDetail->delete();
                    $delivery->save([
                        'goods_num' => $delivery['goods_num'] - $goodsNum,
                        'order_num' => $delivery['order_num'] - 1,
                        'store_num' => $shopNum,
                        'company_order_ids'=>implode(',',$orderIds)
                    ]);
                }
            }
        } catch (\Exception $e) {
            return $this->error('删除失败:' . $e->getMessage());
        }
        return $this->success('删除成功');
    }
}
